package com.ksl.kinglockguard.bitmap;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;

import com.ksl.kinglockguard.domain.MemoryCache;
import com.ksl.kinglockguard.utils.SdcardFileUtil;
import com.lsk.open.core.MyLog;
import com.lsk.open.core.utils.KingsFileUtils;

public class ImageLoader {

	private Context mContext;
	private static Handler mHandler = null;
	public static final int LOCK_ITEM_PICTURE = 0;
	public static final int LOCK_SCREEN_PICTURE = 1; 
	public static final int LOCK_BANNER_PICTURE = 2;
	public static final int LOCK_DESK_ICON = 3;
	public static final int LOCK_BLUR_PICTURE = 4;
	public static final int LOCK_H5_PICTURE = 5;
	private MemoryCache memoryCache = new MemoryCache();
	private Map<ImageView, String> imageViews = Collections
			.synchronizedMap(new WeakHashMap<ImageView, String>());
	// 线程池
	private ExecutorService executorService;
	List<Map<String,Object>> mData=new ArrayList<Map<String,Object>>();
	public static ImageLoader getInstance(Context context){
		return new ImageLoader(context);
	}
	private ImageLoader(Context context) {
		this.mContext = context.getApplicationContext();
		executorService = Executors.newFixedThreadPool(5);
	}
		
	// 最主要的方法
	public void DisplayImage(String url, ImageView imageView, boolean isLoadOnlyFromCache, int type) {
		imageViews.put(imageView, url);
		// 先从内存缓存中查找
		Bitmap bitmap = memoryCache.get(url);
		if (bitmap != null){
			MyLog.i("jyh", "~~~~~~~~先从内存缓存中查找~~~~~~~");
			imageView.setImageBitmap(bitmap);
		}else{
    		// 先从文件缓存中查找是否有
			File f = null;
			try {
				f = SdcardFileUtil.getFile(type, url);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		if (f != null && f.exists()){
    			Bitmap bmp = decodeFile(f,type);
				//显示SD卡中的图片缓存
    			MyLog.i("jyh", "~~~~~~~~显示SD卡中的图片缓存~~~~~~~");
        		if(bmp != null)
        			imageView.setImageBitmap(bmp);
    		}else{
				//线程加载网络图片
    			MyLog.i("jyh", "~~~~~~~~线程加载网络图片~~~~~~~");
    			queuePhoto(url, imageView, type);
        	}
		}
	}
	
	//根据图片的不同类型，存放到SD卡的不同位置
//	public File getFile(int type,String url){
//		File f = null;
//		if(type == LOCK_ITEM_PICTURE)
//			f = KingsFileUtils.getSmallPicFile(url);
//		else if(type == LOCK_BANNER_PICTURE)
//			f = KingsFileUtils.getMiddlePicFile(url);
//		else if(type == LOCK_SCREEN_PICTURE)
//			f = KingsFileUtils.getLargePicFile(url);
//		else if(type == LOCK_DESK_ICON)
//			f = KingsFileUtils.getDeskIconFile(url);
//		else if(type == LOCK_BLUR_PICTURE)
//			f = KingsFileUtils.getLargePicBlurFile(url);
//		else if(type == LOCK_H5_PICTURE)
//			f = KingsFileUtils.getH5PicFile(url);
//		return f;
//	}
	/*
	 * @type
	 * type == LOCK_ITEM_PICTURE     代表请求首页推荐列表的item小图片
	 * type == LOCK_SCREEN_PICTURE   代表请求锁屏的大图片
	 * type == LOCK_FOCUS_PICTURE    代表请求焦点图
	 * type == LOCK_DESK_ICON        代表请求锁屏小图
	 */
	
	public void queuePhoto(String url, ImageView imageView, int type) { 
		PhotoToLoad p = new PhotoToLoad(url, imageView, type);
		executorService.submit(new PhotosLoader(p));
	}

	@SuppressLint("NewApi") 
	private Bitmap getBitmap(String url,int type) {
		MyLog.i("jyh", "~~~~~~getBitmap()~~~~~type~~~"+type);
		File f = null;
		try {
			f = SdcardFileUtil.getFile(type, url);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(!f.getParentFile().exists()){
			boolean rtn = f.getParentFile().mkdirs();
			MyLog.i("wmm", f.getParentFile().getName() + "the resutl of mkdirs is " + rtn);
		}
		// 先从文件缓存中查找是否有
		Bitmap b = null;
		if (f != null && f.exists()){
			b = decodeFile(f,type);
		}
		if (b != null){
			return b;
		}
		// 最后从指定的url中下载图片
		try {
			Bitmap bitmap = null;
			URL imageUrl = new URL(url);
			HttpURLConnection conn = (HttpURLConnection) imageUrl
					.openConnection();
			conn.setConnectTimeout(30000);
			conn.setReadTimeout(30000);
			conn.setInstanceFollowRedirects(true);
			InputStream is = conn.getInputStream();
			OutputStream os = new FileOutputStream(f);
			if(!CopyStream(is, os) && f.exists())
				f.delete();
//			CopyStream(is, os);
			os.close();
			if(mILoadedFinishLister!=null){
				mILoadedFinishLister.dowloadOk(url);
			}
			bitmap = decodeFile(f,type);
			return bitmap;
		} catch (Exception ex) {
			MyLog.e("wmm", "getBitmap catch Exception...\nmessage = " + ex.getMessage());
			return null;
		}
	}
	
	private static long getFileSize(File file) throws Exception
	{
		long size = 0;
		 if (file.exists()){
		 FileInputStream fis = null;
		 fis = new FileInputStream(file);
		 size = fis.available();
		 }
		 else{
		 file.createNewFile();
		 Log.e("获取文件大小","文件不存在!");
		 }
		 return size;
	}
	// decode这个图片并且按比例缩放以减少内存消耗，虚拟机对每张图片的缓存大小也是有限制的
	public static Bitmap decodeFile(File f,int type) {
		try {
			// decode image size
			MyLog.i("jyh", "~~~~~~decodeFile()~~~~~type~~~"+type);
			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(new FileInputStream(f), null, o);

			// Find the correct scale value. It should be the power of 2.
			final int REQUIRED_SIZE = 200;
			int width_tmp = o.outWidth, height_tmp = o.outHeight;
			int scale = 1;
			if(type == LOCK_ITEM_PICTURE || type == LOCK_H5_PICTURE){
				MyLog.i("jyh", "~~~~~~type == LOCK_ITEM_PICTURE~~~~~~~~");
				while (true) {
					if (width_tmp / 2 < REQUIRED_SIZE
							|| height_tmp / 2 < REQUIRED_SIZE)
						break;
					width_tmp /= 2;
					height_tmp /= 2;
					scale *= 2;
				}
			}
			// decode with inSampleSize
			BitmapFactory.Options o2 = new BitmapFactory.Options();
			o2.inSampleSize = scale;
			if(type == LOCK_ITEM_PICTURE || type == LOCK_H5_PICTURE){
				MyLog.i("jyh1", "~~~~~~~~fillet performed~~~~~~~~~~");
				Bitmap bmpp = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
				return fillet(bmpp,3);
			}
			else
				return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
		} catch (FileNotFoundException e) {
		}
		return null;
	}

	// Task for the queue
	private class PhotoToLoad {
		public String url;
		public ImageView imageView;
		public int type;
		
		public PhotoToLoad(String u, ImageView i, int type) {
			url = u;
			imageView = i;
			this.type = type;
		}
	}

	class PhotosLoader implements Runnable {
		PhotoToLoad photoToLoad;

		PhotosLoader(PhotoToLoad photoToLoad) {
			this.photoToLoad = photoToLoad;
		}

		@Override
		public void run() {
			Bitmap bmp = getBitmap(photoToLoad.url,photoToLoad.type);
			memoryCache.put(photoToLoad.url, bmp);
			if(photoToLoad.imageView != null){
				MyLog.i("jyh1", "~~~~photoToLoad.imageView != null~~~~");
				BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
				// 更新的操作放在UI线程中
//				Activity a = (Activity) photoToLoad.imageView.getContext();
//				a.runOnUiThread(bd);
				new Handler(photoToLoad.imageView.getContext().getMainLooper()).post(bd);
			}else{
//				MyLog.i("jyh1", "~~~~photoToLoad.imageView = null~~~~");
//				mHandler.obtainMessage(Constants.GET_LOCKSCREEN_IMAGE, photoToLoad.url).sendToTarget();
			}
		}
	}
	
	public static void setHandler(Handler handler)
	{
		mHandler = handler;
	}

	/**
	 * 防止图片错位
	 * 
	 * @param photoToLoad
	 * @return
	 */
	boolean imageViewReused(PhotoToLoad photoToLoad) {
		String tag = imageViews.get(photoToLoad.imageView);
		if (tag == null || !tag.equals(photoToLoad.url))
			return true;
		return false;
	}

	// 用于在UI线程中更新界面
	class BitmapDisplayer implements Runnable {
		Bitmap bitmap;
		PhotoToLoad photoToLoad;

		public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
			bitmap = b;
			photoToLoad = p;
		}

		public void run() {
			if (imageViewReused(photoToLoad))
				return;
			if (bitmap != null)
				photoToLoad.imageView.setImageBitmap(bitmap);
	
		}
	}

	public void clearCache() {
		memoryCache.clear();
	}

	public static boolean CopyStream(InputStream is, OutputStream os) {
		final int buffer_size = 1024;
		try {
			byte[] bytes = new byte[buffer_size];
			for (;;) {
				int count = is.read(bytes, 0, buffer_size);
				if (count == -1)
					return true;
				os.write(bytes, 0, count);
			}
		} catch (Exception ex) {
			MyLog.e("", "CopyStream catch Exception...");
			return false;
		}
	}
	
	public interface ILoadedFinishLister{
		void dowloadOk(String url);
	}
	
	private ILoadedFinishLister mILoadedFinishLister;
	public ILoadedFinishLister getmILoadedFinishLister() {
		return mILoadedFinishLister;
	}
	public void setmILoadedFinishLister(ILoadedFinishLister mILoadedFinishLister) {
		this.mILoadedFinishLister = mILoadedFinishLister;
	}
	
	@SuppressWarnings("deprecation")
	public static Bitmap fillet(Bitmap bitmap, int roundPx) {
		try {
			// 其原理就是：先建立一个与图片大小相同的透明的Bitmap画板
			// 然后在画板上画出一个想要的形状的区域。
			// 最后把源图片帖上。
			final int width = bitmap.getWidth();
			final int height = bitmap.getHeight();

			Bitmap paintingBoard = Bitmap.createBitmap(width, height,
					Config.ARGB_8888);
			Canvas canvas = new Canvas(paintingBoard);
			canvas.drawARGB(Color.TRANSPARENT, Color.TRANSPARENT,
					Color.TRANSPARENT, Color.TRANSPARENT);

			final Paint paint = new Paint();
			paint.setAntiAlias(true);
			paint.setColor(Color.BLACK);

			clipTop(canvas, paint, roundPx, width, height);
//			clipLeft(canvas, paint, roundPx, width, height);
//			clipRight(canvas, paint, roundPx, width, height);

			paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
			// 帖子图
			final Rect src = new Rect(0, 0, width, height);
			final Rect dst = src;
			canvas.drawBitmap(bitmap, src, dst, paint);
			MyLog.i("jyh1", "~~~~~~~~no exceptions~~~~~~~~~~");
			return paintingBoard;
		} catch (Exception exp) {
			return bitmap;
		}
	}

	private static void clipLeft(final Canvas canvas, final Paint paint,
			int offset, int width, int height) {
		final Rect block = new Rect(offset, 0, width, height);
		canvas.drawRect(block, paint);
		final RectF rectF = new RectF(0, 0, offset * 2, height);
		canvas.drawRoundRect(rectF, offset, offset, paint);
	}

	private static void clipRight(final Canvas canvas, final Paint paint,
			int offset, int width, int height) {
		final Rect block = new Rect(0, 0, width - offset, height);
		canvas.drawRect(block, paint);
		final RectF rectF = new RectF(width - offset * 2, 0, width, height);
		canvas.drawRoundRect(rectF, offset, offset, paint);
	}

	private static void clipTop(final Canvas canvas, final Paint paint,
			int offset, int width, int height) {
		final Rect block = new Rect(0, offset, width, height);
		canvas.drawRect(block, paint);
		final RectF rectF = new RectF(0, 0, width, offset * 2);
		canvas.drawRoundRect(rectF, offset, offset, paint);
	}

	private static void clipBottom(final Canvas canvas, final Paint paint,
			int offset, int width, int height) {
		final Rect block = new Rect(0, 0, width, height - offset);
		canvas.drawRect(block, paint);
		final RectF rectF = new RectF(0, height - offset * 2, width, height);
		canvas.drawRoundRect(rectF, offset, offset, paint);
	}

	private static void clipAll(final Canvas canvas, final Paint paint,
			int offset, int width, int height) {
		final RectF rectF = new RectF(0, 0, width, height);
		canvas.drawRoundRect(rectF, offset, offset, paint);
	}

	
	
}
